package cz.vse.po1715.lode.net.obecne;

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.logging.*;
//import java.net.InetAddress;

/*******************************************************************************
 * Instance třídy {@code Příloha} představují přílohy klíče každého klientského
 * kanálu registrovaný na serveru pomocí selektoru
 * Uchovává dočasná příchozí data herní události a kontroluje kompletnost 
 * hlavičky herní události
 *
 * @author    Dominik KOSTKA
 * @version   0.00.000
 */
public class Příloha
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** počet bajtů v hlavičce síťové události */
    public static final int VELIKOST_HLAVIČKY = 12;
//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================

    /** zapisovač */
    private static Logger log = Logger.getLogger("Příloha");
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================
//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** unikátní id klienta */
    public int IdKlienta;

    /** velikost herní události v bytech */
    public int velikostUdálosti;

    /** hash kód hry, ke které herní událost směřuje */
    public int hashKódHry;

    /** příznak přítomnosti hlavičky v příloze */
    private boolean mášHlavičku;

    /** buffer používaný pro zadržení dat čtených z kanálu */
    public ByteBuffer readBuff;

    /** dočasné úložiště dat herní události před jejich načítáním do události*/
    public byte dataUdálosti[];
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     *Konstruktor inicializuje data události a čtecí buffer
     */
    public Příloha()
    {
        dataUdálosti = new byte[Konstanty.MAX_VELIKOST_UDÁLOSTI];
        readBuff = ByteBuffer.allocateDirect(Konstanty.NET_BUFFER_SIZE);
    }



//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================

    /**
     * zkontroluje zda byla načtena kompletní událost
     * @return true pokud je událost připravena, jinak false
     */
    public boolean událostPřipravena() throws IllegalArgumentException {
	if (zkontrolujHlavičku() && zkontrolujDataUdálosti())
	    return true;
	else
	    return false;
    }
    
    /**
     * vymaže přílohu pro čtení další události
     */
    public void vymaž() {
	mášHlavičku = false;
    }

    /**
     * Zkontroluje, zda je hlavička herní události už kompletní
     * @return true pokud je hlavička plně dostupná, jinak false
     */
    private boolean zkontrolujHlavičku() throws IllegalArgumentException {
	if (mášHlavičku) return true;
	if (readBuff.remaining() >= VELIKOST_HLAVIČKY) {

            // čtení informací z hlavičky
	    IdKlienta = readBuff.getInt();
	    hashKódHry = readBuff.getInt();
	    velikostUdálosti = readBuff.getInt();

	    // kontrola omezení velikosti dat události
	    if (velikostUdálosti > Konstanty.MAX_VELIKOST_UDÁLOSTI)
		throw new IllegalArgumentException("Hlavička uvadí velikost události (" +
						   velikostUdálosti + ") větší než " +
                                                   "maximální velikost události(" +
						   Konstanty.MAX_VELIKOST_UDÁLOSTI + ")");
	    mášHlavičku = true;
	    return true;
	}
	else {
	    return false;
	}
    }

    /**
     * zkontroluje, zda jsou data herní události kompletní
     */
    private boolean zkontrolujDataUdálosti() {
	if (readBuff.remaining() >= velikostUdálosti) {
 	    try {
  		readBuff.get(dataUdálosti, 0, velikostUdálosti);
 	    }
 	    catch (BufferUnderflowException bue) {
 		log.info("buffer podtekl");
 	    }
	    return true;
	}
	else {
	    return false;
	}
    }
//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTOVACÍ METODY A TŘÍDY ==================================================
//
//    /***************************************************************************
//     * Testovací metoda.
//     */
//    public static void test()
//    {
//        Příloha inst = new Příloha();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}
